package models;

import java.io.BufferedReader;
import java.io.FileReader;

import metamodels.Metamodel;
import parser.generic.Node;
import utils.Utils;
import errors.Error;

public class Model extends Node implements K{

	private String modelName;
	private String metamodelName;
	private Instances instances;

	public Model(String mName, String mmName, Instances instances) {
		this.modelName = mName;
		this.metamodelName = mmName;
		this.instances = instances;
	}

	@Override
	public String toString() {
		return "model " + modelName + " : " + metamodelName + " = {\n" + instances + "\n}";
	}

	@Override
	public String toK(Metamodel metamodel) {

		String out = "";
		
		out += "load classdiagram\n\n";
		out += "module MODEL is including META-MODEL\n\n";
		
		out += "syntax #Id ::= x | y | run | p\n\n";
		
		out += "syntax #Id ::= " + modelName  + " " + instances.getObjectNames() + "\n\n";
		
		out += getConfiguration() + "\n\n";
		
		out += "macro initConfig = <T>\n\t<oclConstraints> \n\t\t" + metamodel.getConstraints() + "\n\t\t.List\n\t</oclConstraints>\n";
		out += "\t<model>\n\t\t<modelName> " + modelName + " </modelName>\n";
		out += instances.toK(metamodel, "\t\t");
		out += "\n\t</model>\n";
		
		out += "<k>  checkConformance </k>\n";
		out += "<result>  .List </result>\n";
		out += "</T>\n";
		out += "syntax K ::= checkConformance\n";
		out += "rule <k> checkConformance => checkOCL(OCL:List) ...</k>\n<oclConstraints> OCL </oclConstraints>\n";
		out += "syntax K ::= checkOCL ( List )\n";
		out += "rule <k> checkOCL(.) => .K ...</k>   [:structural:]\n";
		out += "syntax ListItem ::= `OCL ( Exp ) | result ( #Magma )\n";
		out += "rule <k> checkOCL( OCL(E:Exp) L:List) =>  E~>checkOCL(L) ...</k> [:structural:]\n";
		out += "rule <k> val:#Magma => .K ...</k> <result>... .List => res ( val ) </result>  [:structural:]\n\n"; 
		out += "end module";
		
		return out;
	}

	private String getConfiguration() {
		try {
			StringBuffer fileData = new StringBuffer(1000);
			BufferedReader reader = new BufferedReader(new FileReader(
					Utils.CONFIGURATION));
			char[] buf = new char[1024];
			int numRead = 0;
			while ((numRead = reader.read(buf)) != -1) {
				String readData = String.valueOf(buf, 0, numRead);
				fileData.append(readData);
				buf = new char[1024];
			}
			reader.close();
			return fileData.toString();
		} catch (Exception e) {
			System.out.println(e.getLocalizedMessage());
			Error.report("Internal error!");
		}

		return "";
	}
}
